home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 24 / AACD 24.iso / AACD / Sound / LAME / WarpOS / src / misc / ath.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-05  |  26.6 KB  |  840 lines

  1. /* $Id: ath.c,v 1.12 2000/12/05 15:37:26 aleidinger Exp $ */
  2. /*
  3.  * Known bugs (sorted by importance): 
  4.  *     - human delay (ca. 200 ms or more???) and buffering delay (341 ms @48 kHz/64 KByte)
  5.  *       should be subtracted
  6.  *     - error handling
  7.  *     - cos slope on direction changes
  8.  *     - calibration file of soundcard/amplifier/head phone
  9.  *     - worse handling
  10.  *     - +/- handling via mouse (do you have code?) in a dark room
  11.  *     - ENTER as direction change
  12.  *     - finer precalculated ATH for pre-emphasis
  13.  */
  14.  
  15. /* 
  16.  * Suggested level ranges:
  17.  *     180 Hz...13.5 kHz:  50...70 dB
  18.  *     100 Hz...15.0 kHz:  40...70 dB
  19.  *      70 Hz...16.0 kHz:  30...70 dB
  20.  *      45 Hz...16.5 kHz:  20...70 dB
  21.  *      30 Hz...17.5 kHz:  10...70 dB
  22.  *      25 Hz...18.0 kHz:   5...75 dB
  23.  *      20 Hz...19.0 kHz:   0...80 dB
  24.  *      16 Hz...20.0 kHz: -10...80 dB
  25.  */
  26.  
  27. #ifdef HAVE_CONFIG_H
  28. # include <config.h>
  29. #endif
  30.  
  31. #include <assert.h>
  32. #include <errno.h>
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <unistd.h>
  36. #include <string.h>
  37. #include <fcntl.h>
  38. #include <limits.h>
  39. #include <termios.h>
  40. #include <math.h>
  41. #include <time.h>
  42. #include <signal.h>
  43. #include <sys/ioctl.h>
  44. #include <sys/time.h>
  45. #include <sys/types.h>
  46. #include <sys/stat.h>
  47. #ifdef HAVE_SYS_SOUNDCARD_H
  48. # include <sys/soundcard.h>
  49. #elif defined(HAVE_LINUX_SOUNDCARD_H)
  50. # include <linux/soundcard.h>
  51. #else
  52. # error no soundcard include
  53. #endif
  54.  
  55.      
  56.  
  57. #define AUDIO_DEVICE       "/dev/dsp"
  58. //#define COOLEDIT_FILE      "/mnt/dosd/cooledit.wav"
  59. #define DELAY_UNTIL_XCHG   2.5
  60. #define TURN_STEPS       2400
  61.  
  62. /******************************************************************************************************
  63.  *  soundcard stuff
  64.  ******************************************************************************************************/
  65.  
  66. const double dither_coeff [] [16] = {
  67.     {  /* 48 kHz */ 3.35185352775391591311,  4.24914379295482032978,  1.78042251729150153086, -0.92601381419186201184, -1.37308596104182343645, -1.85951915999247704829, -3.28074437872632330526, -3.05496670185702990882, -1.22855462839450528837, -0.30291531959171267015, -0.18598486195652600770,  0.42010512205702003790,  0.92278786111368653452,  0.62102380451771775193,  0.14312897206650044828, -0.00454721508203927746 },
  68.     {  /* 56 kHz */ 3.86404134982280628749,  6.67195592701613291071,  5.90576195467245802046,  1.57589705921487261981, -2.10618201389737372178, -2.74191788822507184395, -2.62175070636849999396, -3.78505226463032808863, -4.45698848578010438284, -2.76825966243460536110, -0.26509931375584007312,  0.67853812028968716799,  0.17633528441477021892, -0.28511417191837823770, -0.21866605100975608470, -0.04751674094456833719 },
  69.     {  /* 64 kHz */ 4.09276938880098092172,  8.27424044674659812937, 10.11503162292146762880,  7.19159801569544317353,  1.39770070291739556523, -2.86595901981244688601, -3.76567274050094691362, -3.58051445684472378298, -4.78262917738758022539, -6.53075750894777650899, -6.31330514306857055627, -3.69971382767763534195, -0.78125094191744878298,  0.59027508113837267217,  0.53500264009607367648,  0.14860043567206217506 },
  70.     {  /* 72 kHz */ 4.13833553801985235465,  9.02461778089340082437, 12.93090366932740510782, 12.66372285767699051948,  7.76122176702274149630,  1.30617257555732278296, -2.92859120887121285358, -4.02438598495837830627, -4.16673068132491936262, -5.55618065300129916574, -7.82657788611231653103, -8.83055904466106668035, -7.34884789347713815672, -4.33977664906048314891, -1.67711310288611975398, -0.33086687044710235420 },
  71.     {  /* 80 kHz */ 4.22135293342667005517,  9.76639846582539722375, 15.46562682418357478290, 17.54378549927855248346, 13.29112084313158963396,  3.51512441998252657470, -7.51025671462502577300,-14.84164320864536219368,-16.10306907358826504148,-12.54775907691866414402, -7.40560667268782655149, -3.34708029482052565732, -1.19572214872925790860, -0.39582185216275086786, -0.14803160816846603424, -0.04292818488627011881 },
  72.     {  /* 88 kHz */ 4.18521467865996935325,  9.96765821475909556942, 16.91905760389390617551, 21.74016824668913557689, 20.96457146354060682367, 13.28640453421253890542,  0.85116933842171101587,-11.66054516261007127469,-19.62750656985581800169,-20.98831962473015904508,-16.95374072505042825458,-10.68848180295390154146, -5.17169792984369678908, -1.79975409439650319129, -0.38057073791415898674, -0.02672653932844656975 },
  73.     {  /* 96 kHz */ 4.09418877324899473189,  9.77977364010870211207, 17.10120082680385341159, 23.37356217615995036818, 25.27121942060722374276, 20.64059991613550174190,  9.99721445051475610371, -3.39833000550997938512,-15.03410054392933377278,-21.36704201000683067679,-21.40772859969388741685,-16.79355426136657673808,-10.48570200688141622163, -5.07642951516127438486, -1.75555240936989159436, -0.33817997298586054131 },
  74. };
  75.  
  76. typedef struct {
  77.     const char*    device;
  78.     int            fd;
  79.     long double    sample_freq;
  80.     const double*  dither;
  81.     int            channels;
  82.     int            bits;
  83. } soundcard_t;
  84.  
  85. typedef signed short  sample_t;
  86. typedef sample_t      stereo_t [2]; 
  87.  
  88. int  open_soundcard ( 
  89.     soundcard_t* const  k, 
  90.     const char*         device, 
  91.     const int           channels,
  92.     const int           bits, 
  93.     const long double   freq )
  94. {
  95.     int  arg;
  96.     int  org;
  97.     int  index;
  98.     int  status;
  99.     
  100.     k->device = device;
  101.     if ( -1 == (k->fd = open ( k->device, O_WRONLY )) ) {
  102.         perror("opening of audio device failed");
  103.     return -1;
  104.     }
  105.     
  106.     if ( -1 == (status = ioctl (k->fd, SOUND_PCM_SYNC, 0))) {
  107.         fprintf ( stderr, "%s: SOUND_PCM_SYNC ioctl failed: %s\n", k->device, strerror (errno));
  108.         return -1;
  109.     }
  110.  
  111.     org = arg = channels;
  112.     if ( -1 == (status = ioctl (k->fd, SOUND_PCM_WRITE_CHANNELS, &arg)) ) {
  113.     fprintf ( stderr, "%s: SOUND_PCM_WRITE_CHANNELS (%d) ioctl failed: %s\n" , k->device, channels, strerror (errno) );
  114.     return -1;
  115.     }
  116.     if (arg != org) {
  117.     fprintf ( stderr, "%s: unable to set number of channels: %d instead of %d\n", k->device, arg, org );
  118.     return -1;
  119.     }
  120.     k->channels = arg;
  121.     
  122.     org = arg = bits;
  123.     if ( -1 == (status = ioctl (k->fd, SOUND_PCM_WRITE_BITS, &arg)) ) {
  124.     fprintf ( stderr, "%s: SOUND_PCM_WRITE_BITS ioctl failed\n", k->device );
  125.     return -1;
  126.     }
  127.     if (arg != org) {
  128.     fprintf ( stderr, "%s: unable to set sample size: %d instead of %d\n", k->device, arg, org );
  129.     return -1;
  130.     }
  131.     k->bits = arg;
  132.  
  133.     org = arg = k->bits <= 8  ?  AFMT_U8  :  AFMT_S16_LE;
  134.     if ( -1 == ioctl (k->fd, SNDCTL_DSP_SETFMT, &arg) ) {
  135.     fprintf ( stderr, "%s: SNDCTL_DSP_SETFMT ioctl failed\n", k->device );
  136.     return -1;
  137.     }
  138.     if ((arg & org) == 0) {
  139.     fprintf ( stderr, "%s: unable to set data format\n", k->device );
  140.     return -1;
  141.     }
  142.     
  143.     org = arg = (int) floor ( freq + 0.5 );
  144.     if ( -1 == (status = ioctl (k->fd, SOUND_PCM_WRITE_RATE, &arg)) ) {
  145.     fprintf ( stderr, "%s: SOUND_PCM_WRITE_WRITE ioctl failed\n", k->device );
  146.     return -1;
  147.     }
  148.     k->sample_freq = (long double)arg;
  149.     index          = (arg - 44000) / 8000;
  150.     if ( index <                                           0 ) index = 0;
  151.     if ( index >= sizeof(dither_coeff)/sizeof(*dither_coeff) ) index = sizeof(dither_coeff)/sizeof(*dither_coeff) - 1;
  152.     k->dither      = dither_coeff [ index ];
  153.     return 0;
  154. }
  155.  
  156. int  play_soundcard    ( soundcard_t* const k, stereo_t* samples, size_t length )
  157. {
  158.     size_t  bytes = length * sizeof (*samples);
  159.     
  160. #ifdef COOLEDIT_FILE
  161.     static int fd = -1;
  162.     if ( fd < 0 ) fd = open ( COOLEDIT_FILE, O_WRONLY | O_CREAT );
  163.     write ( fd, samples, bytes );
  164. #endif    
  165.     
  166.     return write ( k->fd, samples, bytes ) == bytes  ?  0  :  -1;
  167. }
  168.  
  169. int  close_soundcard   ( soundcard_t* const k )
  170. {
  171.     return close (k->fd);
  172. }
  173.  
  174.  
  175. /******************************************************************************************************
  176.  *  frequency stuff
  177.  ******************************************************************************************************/
  178.  
  179. typedef enum {
  180.     linear    = 0,
  181.     logarithm = 1,
  182.     square    = 2,
  183.     cubic     = 3,
  184.     erb       = 4,
  185.     recip     = 5
  186. } genmode_t;
  187.  
  188. static long double linear_f        ( long double x ) { return x > 0.L  ?  x             :  0.0L; }
  189. static long double logarithm_f     ( long double x ) { return x > 0.L  ?  log10 (x)     : -3.5L; }
  190. static long double square_f        ( long double x ) { return x > 0.L  ?  sqrt (x)      :  0.0L; }
  191. static long double cubic_f         ( long double x ) { return x > 0.L  ?  pow (x,1/3.)  :  0.0L; }
  192. static long double erb_f           ( long double x ) { return log (1. + 0.00437*x); }
  193. static long double recip_f         ( long double x ) { return x > 1.L  ?  1.L/x         :  1.0L; }
  194.  
  195. static long double inv_linear_f    ( long double x ) { return x;  }
  196. static long double inv_logarithm_f ( long double x ) { return pow (10., x);  }
  197. static long double inv_square_f    ( long double x ) { return x*x;  }
  198. static long double inv_cubic_f     ( long double x ) { return x*x*x;  }
  199. static long double inv_erb_f       ( long double x ) { return (exp(x) - 1.) * (1./0.00437); }
  200. static long double inv_recip_f     ( long double x ) { return x > 1.L  ?  1.L/x         :  1.0L; }
  201.  
  202. typedef long double (*converter_fn_t) ( long double );
  203.  
  204. const converter_fn_t  func     [] = { linear_f,     logarithm_f,     square_f,     cubic_f    , erb_f    , recip_f     };
  205. const converter_fn_t  inv_func [] = { inv_linear_f, inv_logarithm_f, inv_square_f, inv_cubic_f, inv_erb_f, inv_recip_f };
  206.  
  207. typedef struct {
  208.     genmode_t      genmode;
  209.     long double    start_freq;
  210.     long double    stop_freq;
  211.     long double    sample_freq;
  212.     unsigned long  duration;
  213.  
  214.     long double    phase;
  215.     long double    param1;
  216.     long double    param2;
  217.     unsigned long  counter; 
  218. } generator_t;
  219.  
  220. int  open_generator ( 
  221.     generator_t* const  g,
  222.     const soundcard_t*  const s,
  223.     const genmode_t     genmode, 
  224.     const long double   duration, 
  225.     const long double   start_freq, 
  226.     const long double   stop_freq )
  227. {
  228.     g->sample_freq = s->sample_freq;
  229.     g->genmode     = genmode;
  230.     g->start_freq  = start_freq;
  231.     g->stop_freq   = stop_freq;
  232.     g->duration    = (unsigned long) floor ( duration * g->sample_freq + 0.5 );
  233.     
  234.     if ( g->duration < 2 )
  235.     return -1;
  236.  
  237.     if ( g->genmode >= sizeof (func)/sizeof(*func) )
  238.     return -1;
  239.     
  240.     g->param1 = func [g->genmode] ( g->start_freq / g->sample_freq );
  241.     g->param2 = ( func [ g->genmode ] ( g->stop_freq / g->sample_freq ) - g->param1 ) 
  242.           / ( g->duration - 1 );
  243.     g->phase  = 0.L;
  244.     g->counter= 0;
  245.     
  246.     return 0;
  247. }
  248.  
  249. long double  iterate_generator ( generator_t* const g )
  250. {
  251.     long double  freq;
  252.     
  253.     freq = inv_func [ g->genmode ] ( g->param1 + g->counter++ * g->param2 );
  254.     
  255.     g->phase += freq;
  256.     if (g->phase > 15.)
  257.     g->phase -= 16.;
  258.     return sin ( 2.*M_PI * g->phase );
  259. }
  260.  
  261. long double  get_sine ( generator_t* const g )
  262. {
  263.     return sin ( 2.*M_PI * g->phase );
  264. }
  265.  
  266. long double  get_cosine ( generator_t* const g )
  267. {
  268.     return cos ( 2.*M_PI * g->phase );
  269. }
  270.  
  271.  
  272. long double  frequency ( const generator_t* const g )
  273. {
  274.     return inv_func [ g->genmode ] ( g->param1 + g->counter * g->param2 ) * g->sample_freq;
  275. }
  276.  
  277. int  close_generator ( generator_t* const g )
  278. {
  279.     return 0;
  280. }
  281.  
  282. /******************************************************************************************************
  283.  *  amplitude stuff
  284.  ******************************************************************************************************/
  285.  
  286. typedef enum {
  287.     up         = 0,
  288.     down       = 1,
  289.     turn_up    = 2,
  290.     turn_down  = 3,
  291.     still_up   = 4,
  292.     still_down = 5,
  293.     change     = 6
  294. } direction_t;
  295.     
  296.     
  297. typedef struct {
  298.     long double    sample_freq;
  299.     direction_t    direction;            // down, up, still_up, still_down, turn_down, turn_up
  300.     int            multiplier;           // -TURN_STEPS: down, +TURN_STEPS up
  301.     long double    amplitude;
  302.     long double    delta_amplitude;
  303.     long           direction_change;
  304. } amplitude_t;
  305.  
  306. int  open_amplifier ( 
  307.     amplitude_t* const        a,
  308.     const soundcard_t* const  s,
  309.     const long double         start_ampl,
  310.     const double              dB_per_sec )
  311. {
  312.     a->sample_freq      = s->sample_freq;
  313.     a->direction        = up;
  314.     a->multiplier       = +TURN_STEPS;
  315.     a->amplitude        = start_ampl * 32767.;
  316.     a->delta_amplitude  = dB_per_sec * 0.1151292546497022842 / s->sample_freq / TURN_STEPS;
  317.     a->direction_change = 0;
  318.     
  319.     srand ( time (NULL) );
  320.     return 0;
  321. }
  322.  
  323. long double iterate_amplifier ( amplitude_t* const a )
  324. {
  325.     switch ( a->direction ) {
  326.     case still_up:
  327.         assert (a->multiplier == +TURN_STEPS);
  328.         if (a->direction_change > 0 )
  329.         a->direction_change--;
  330.     else
  331.         a->direction = turn_down;
  332.     break;
  333.     case still_down:
  334.         assert (a->multiplier == -TURN_STEPS);
  335.         if (a->direction_change > 0 )
  336.         a->direction_change--;
  337.     else
  338.         a->direction = turn_up;
  339.     break;
  340.     case turn_up:
  341.         assert (a->direction_change == 0);
  342.     if ( a->multiplier < +TURN_STEPS )
  343.         a->multiplier++;
  344.     else
  345.         a->direction = up;
  346.     break;
  347.     case turn_down:
  348.         assert (a->direction_change == 0);
  349.     if ( a->multiplier > -TURN_STEPS )
  350.         a->multiplier--;
  351.     else
  352.         a->direction = down;
  353.     break;
  354.     case up:
  355.         assert (a->multiplier == +TURN_STEPS);
  356.         assert (a->direction_change == 0);
  357.     break;
  358.     case down:
  359.         assert (a->multiplier == -TURN_STEPS);
  360.         assert (a->direction_change == 0);
  361.     break;
  362.     default:
  363.     fprintf ( stderr, "\n\r*** Bug! ***\n");
  364.     break;
  365.     }
  366.  
  367.     a->amplitude *= 1.L + a->delta_amplitude * a->multiplier;
  368.     return a->amplitude;         
  369. }
  370.  
  371. long double amplitude ( const amplitude_t* const a )
  372. {
  373.     return a->amplitude / 32767.;
  374. }
  375.  
  376. int change_direction ( amplitude_t* const a, direction_t new_direction )
  377. {
  378.     switch ( new_direction ) {
  379.     case up:
  380.         if (a->direction == down) {
  381.         a->direction = still_down;
  382.     } else {
  383.         fprintf ( stderr, "Direction not down, so ignored\n" );
  384.         return -1;
  385.     }
  386.     break;
  387.     case down:
  388.         if (a->direction == up) {
  389.         a->direction = still_up;
  390.     } else {
  391.         fprintf ( stderr, "Direction not up, so ignored\n" );
  392.         return -1;
  393.     }
  394.     break;
  395.     case change:
  396.         switch ( a->direction ) {
  397.         case up:
  398.         a->direction = still_up;
  399.         break;
  400.     case down:
  401.         a->direction = still_down;
  402.         break;
  403.     default:
  404.         fprintf ( stderr, "Direction still changing, so ignored\n" );
  405.         return -1;
  406.     }
  407.     break;
  408.     
  409.     default:
  410.     fprintf ( stderr, "Direction unknown, so ignored\n" );
  411.     return -1;
  412.     }
  413.  
  414.     a->direction_change = 1 + rand () * (a->sample_freq * DELAY_UNTIL_XCHG / RAND_MAX);
  415.     return 0;
  416. }
  417.  
  418. int  close_amplifier ( amplitude_t* const a )
  419. {
  420.     return 0;
  421. }
  422.  
  423.  
  424. double ATH ( double freq )
  425. {
  426.     static float tab [] = {
  427.         /*    10.0 */  96.69, 96.69, 96.26, 95.12,
  428.         /*    12.6 */  93.53, 91.13, 88.82, 86.76,
  429.         /*    15.8 */  84.69, 82.43, 79.97, 77.48,
  430.         /*    20.0 */  74.92, 72.39, 70.00, 67.62,
  431.         /*    25.1 */  65.29, 63.02, 60.84, 59.00,
  432.         /*    31.6 */  57.17, 55.34, 53.51, 51.67,
  433.         /*    39.8 */  50.04, 48.12, 46.38, 44.66,
  434.         /*    50.1 */  43.10, 41.73, 40.50, 39.22,
  435.         /*    63.1 */  37.23, 35.77, 34.51, 32.81,
  436.         /*    79.4 */  31.32, 30.36, 29.02, 27.60,
  437.         /*   100.0 */  26.58, 25.91, 24.41, 23.01,
  438.         /*   125.9 */  22.12, 21.25, 20.18, 19.00,
  439.         /*   158.5 */  17.70, 16.82, 15.94, 15.12,
  440.         /*   199.5 */  14.30, 13.41, 12.60, 11.98,
  441.         /*   251.2 */  11.36, 10.57,  9.98,  9.43,
  442.         /*   316.2 */   8.87,  8.46,  7.44,  7.12,
  443.         /*   398.1 */   6.93,  6.68,  6.37,  6.06,
  444.         /*   501.2 */   5.80,  5.55,  5.29,  5.02,
  445.         /*   631.0 */   4.75,  4.48,  4.22,  3.98,
  446.         /*   794.3 */   3.75,  3.51,  3.27,  3.22,
  447.         /*  1000.0 */   3.12,  3.01,  2.91,  2.68,
  448.         /*  1258.9 */   2.46,  2.15,  1.82,  1.46,
  449.         /*  1584.9 */   1.07,  0.61,  0.13, -0.35,
  450.         /*  1995.3 */  -0.96, -1.56, -1.79, -2.35,
  451.         /*  2511.9 */  -2.95, -3.50, -4.01, -4.21,
  452.         /*  3162.3 */  -4.46, -4.99, -5.32, -5.35,
  453.         /*  3981.1 */  -5.13, -4.76, -4.31, -3.13,
  454.         /*  5011.9 */  -1.79,  0.08,  2.03,  4.03,
  455.         /*  6309.6 */   5.80,  7.36,  8.81, 10.22,
  456.         /*  7943.3 */  11.54, 12.51, 13.48, 14.21,
  457.         /* 10000.0 */  14.79, 13.99, 12.85, 11.93,
  458.         /* 12589.3 */  12.87, 15.19, 19.14, 23.69,
  459.         /* 15848.9 */  33.52, 48.65, 59.42, 61.77,
  460.         /* 19952.6 */  63.85, 66.04, 68.33, 70.09,
  461.         /* 25118.9 */  70.66, 71.27, 71.91, 72.60,
  462.     };
  463.     double    freq_log;
  464.     double    dB;
  465.     unsigned  index;
  466.     
  467.     if ( freq <    10. ) freq =    10.;
  468.     if ( freq > 25000. ) freq = 25000.;
  469.     
  470.     freq_log = 40. * log10 (0.1 * freq);   /* 4 steps per third, starting at 10 Hz */
  471.     index    = (unsigned) freq_log;
  472.     assert ( index < sizeof(tab)/sizeof(*tab) );
  473.     dB = tab [index] * (1 + index - freq_log) + tab [index+1] * (freq_log - index);
  474.     return pow ( 10., 0.05*dB );
  475. }
  476.  
  477. /******************************************************************************************************
  478.  *  keyboard stuff
  479.  ******************************************************************************************************/
  480.  
  481. typedef struct {
  482.     int             init;
  483.     struct termios  stored_setting;
  484.     struct termios  current_setting;
  485. } keyboard_t;
  486.  
  487. static keyboard_t* __k;
  488.  
  489. /* Restore term-settings to those saved when term_init was called */
  490.  
  491. static void  term_restore (void)
  492. {
  493.     tcsetattr ( 0, TCSANOW, &(__k->stored_setting) );
  494. }  /* term_restore */
  495.  
  496. /* Clean up terminal; called on exit */
  497.  
  498. static void  term_exit ( int sig )
  499. {
  500.     term_restore ();
  501. }  /* term_exit */
  502.  
  503. /* Will be called when ctrl-Z is pressed, this correctly handles the terminal */
  504.  
  505. static void  term_ctrl_z ( int sig )
  506. {
  507.     signal ( SIGTSTP, term_ctrl_z );
  508.     term_restore ();
  509.     kill ( getpid(), SIGSTOP );
  510. }  /* term_ctrl_z */
  511.  
  512. /* Will be called when application is continued after having been stopped */
  513.  
  514. static void  term_cont ( int sig )
  515. {
  516.     signal ( SIGCONT, term_cont );
  517.     tcsetattr ( 0, TCSANOW, &(__k->current_setting) );
  518. } /* term_cont() */
  519.  
  520. int  open_keyboard    ( keyboard_t* const k )
  521. {
  522.     __k = k;
  523.     tcgetattr ( 0, &(k->stored_setting) );
  524.     tcgetattr ( 0, &(k->current_setting) );
  525.  
  526.     signal ( SIGINT,  term_exit   );       /* We _must_ clean up when we exit */
  527.     signal ( SIGQUIT, term_exit   );
  528.     signal ( SIGTSTP, term_ctrl_z );       /* Ctrl-Z must also be handled     */
  529.     signal ( SIGCONT, term_cont   );
  530. //  atexit ( term_exit );
  531.  
  532.     /* One or more characters are sufficient to cause a read to return */
  533.     cfmakeraw ( &(k->current_setting) );
  534.     k->current_setting.c_oflag     |= ONLCR | OPOST;  /* enables NL => CRLF on output */
  535.     
  536.     tcsetattr ( 0, TCSANOW, &(k->current_setting) );
  537.     return 0;
  538. }
  539.  
  540. int  getchar_keyboard ( keyboard_t* const k )
  541. {
  542.     struct timeval  t;
  543.     fd_set          fd [1];
  544.     int             ret;
  545.     unsigned char   c;
  546.  
  547.     FD_SET (0, fd);
  548.     t.tv_sec  = 0;
  549.     t.tv_usec = 0;
  550.  
  551.     ret = select ( 1, fd, NULL, NULL, &t );
  552.     
  553.     switch ( ret ) {
  554.     case  0:
  555.         return -1;
  556.     case  1:
  557.         ret = read (0, &c, 1);
  558.         return ret == 1  ?  c  :  -1;
  559.     default:
  560.         return -2;
  561.     }
  562. }
  563.  
  564. int  close_keyboard   ( keyboard_t* const k )
  565. {
  566.     term_restore ();
  567.     return 0;
  568. }
  569.  
  570.  
  571. /******************************************************************************************************
  572.  *  reporting stuff
  573.  ******************************************************************************************************/
  574.  
  575. int  report_open ( void )
  576. {
  577.     static char buff [32767];
  578.     fflush  ( stdout );
  579.     setvbuf ( stdout, buff, _IOFBF, sizeof(buff) );
  580.     return 0;
  581. }
  582.  
  583. int  report ( const generator_t* const g, const amplitude_t* const a )
  584. {
  585.     static double  last_freq  = -1.;
  586.     static double  last_level = -1.;
  587.     double         freq;
  588.     double         level;
  589.  
  590.     freq  = frequency (g);
  591.     level = 20. * log10 (amplitude (a) * ATH (freq) ) + 80.;
  592.     
  593.     if ( last_freq >= 0 )
  594.         printf ( "%11.3f %8.2f\n", sqrt (freq*last_freq), 0.5 * (level+last_level) );
  595.     printf ( "# %9.3f %8.2f\n", freq, level );
  596.     
  597.     fflush ( stdout );
  598.     
  599.     last_freq  = freq;
  600.     last_level = level;
  601.     return 0;
  602. }
  603.  
  604. int  report_close ( void )
  605. {
  606.     printf ( "%%%%\n\n" );
  607.     fflush  ( stdout );
  608.     close ( dup ( fileno(stdout) ) );
  609.     setvbuf ( stdout, NULL, _IONBF, 0 );
  610.     return 0;
  611. }
  612.  
  613.  
  614. /******************************************************************************************************
  615.  *  main stuff
  616.  ******************************************************************************************************/
  617.  
  618. typedef enum { 
  619.     left     = 0, 
  620.     right    = 1, 
  621.     phase0   = 2, 
  622.     both     = 2,
  623.     phase90  = 3, 
  624.     phase180 = 4, 
  625.     phasemod = 5 
  626. } earmode_t;
  627.  
  628. static long double scalar ( const double* a, const double* b )
  629. {
  630.     return  a[ 0]*b[ 0] + a[ 1]*b[ 1] + a[ 2]*b[ 2] + a[ 3]*b[ 3]
  631.            +a[ 4]*b[ 4] + a[ 5]*b[ 5] + a[ 6]*b[ 6] + a[ 7]*b[ 7]
  632.            +a[ 8]*b[ 8] + a[ 9]*b[ 9] + a[10]*b[10] + a[11]*b[11]
  633.            +a[12]*b[12] + a[13]*b[13] + a[14]*b[14] + a[15]*b[15];
  634. }
  635.  
  636. int experiment ( generator_t* const  g,
  637.          amplitude_t* const  a,
  638.          keyboard_t*  const  k,
  639.          soundcard_t* const  s,
  640.          earmode_t           earmode )
  641. {    
  642.     long           i;
  643.     int            j;
  644.     stereo_t       samples [512];
  645.     static double  quant_errors [2] [16];
  646.     long double    val;
  647.     double         ampl;
  648.     long           ival;
  649.     
  650.     fprintf ( stderr, "\r+++  up  +++" );
  651.     for ( i = 0; i < g->duration; i += sizeof(samples)/sizeof(*samples) ) {
  652.         fprintf ( stderr, "%3lu%%\b\b\b\b", i*100lu/g->duration );
  653.     
  654.     for (j = 0; j < sizeof(samples)/sizeof(*samples); j++ ) {
  655.         ampl = iterate_amplifier (a) * ATH (frequency (g));
  656.         val  = ampl * iterate_generator (g);
  657.         ival = (long) floor ( val + 0.5 + scalar (quant_errors[0], s->dither) );
  658.         
  659.         if ( ival != (sample_t) ival ) {
  660.         report (g, a);
  661.         fprintf ( stderr, "\rOverrun     \n\n" );
  662.         return -1;
  663.         }
  664.         memmove ( & quant_errors [0] [1], & quant_errors [0] [0], 
  665.                   sizeof(quant_errors[0]) - sizeof(quant_errors[0][0]) );
  666.         quant_errors [0] [0] = val - ival; 
  667.         switch ( earmode ) {
  668.         case both: 
  669.             samples [j] [0] = samples [j] [1] = ival; 
  670.         break;
  671.         case left: 
  672.             samples [j] [0] = ival;
  673.         samples [j] [1] = 0; 
  674.         break;
  675.         case right: 
  676.             samples [j] [0] = 0;
  677.         samples [j] [1] = ival; 
  678.         break;
  679.         case phase180: 
  680.             samples [j] [0] = ival == -32768 ? 32767 : -ival;
  681.         samples [j] [1] = +ival; 
  682.         break;
  683.         case phase90:
  684.             samples [j] [0] = ival;
  685.             val  = ampl * get_cosine (g);
  686.             ival = (long) floor ( val + 0.5 + scalar (quant_errors[1], s->dither) );
  687.             if ( ival != (sample_t) ival ) {
  688.             report (g, a);
  689.             fprintf ( stderr, "\rOverrun     \n\n" );
  690.             return -1;
  691.             }
  692.             memmove ( & quant_errors [1] [1], & quant_errors [1] [0], 
  693.                   sizeof(quant_errors[1]) - sizeof(quant_errors[1][0]) );
  694.               quant_errors [1] [0] = val - ival; 
  695.             samples [j] [1] = ival;
  696.         break;
  697.         default:
  698.             assert (0);
  699.         return -1;
  700.         }
  701.     }
  702.     play_soundcard ( s, samples, sizeof(samples)/sizeof(*samples) );
  703.     if ( amplitude (a) * ATH (frequency (g)) <= 3.16227766e-6 ) {
  704.             report (g, a);
  705.         fprintf ( stderr, "\rUnderrun      \n\n" );
  706.         return -1;
  707.     }
  708.     
  709.     switch ( getchar_keyboard (k) ) {
  710.     case '+':
  711.         fprintf ( stderr, "\r+++  up  +++" );
  712.         report (g, a);
  713.         change_direction ( a, up );
  714.         break;
  715.     case '-':
  716.         fprintf ( stderr, "\r--- down ---" );
  717.             report (g, a);
  718.         change_direction ( a, down );
  719.         break;
  720.     case '\r':
  721.     case '\n':
  722.         fprintf ( stderr, "\r** change **" );
  723.             report (g, a);
  724.         change_direction ( a, change );
  725.         break;
  726.     case 'C'&0x1F:
  727.     case 'q':
  728.     case 'Q':
  729.     case 'x':
  730.     case 'X':
  731.         fprintf ( stderr, "\rBreak       \n\n" );
  732.         fflush  ( stderr );
  733.         return -1;
  734.     default:
  735.         fprintf ( stderr, "\a" );
  736.         break;
  737.     case -1:
  738.         break;
  739.     }
  740.     }
  741.     
  742.     fprintf ( stderr, "\rReady       \n\n" );
  743.     return 0;
  744. }
  745.  
  746. static void usage ( void )
  747. {
  748.     static const char help[] = 
  749.         "'Absolute Threshold of Hearing' -- Version 0.07   (C) Frank Klemm 2000\n"
  750.     "\n"
  751.     "usage:\n" 
  752.     "    ath  type minfreq maxfreq duration ampl_speed [start_level [earmode] > reportfile\n"
  753.     "\n"
  754.     "         type:         linear, logarithm, square, cubic, erb, recip\n"
  755.     "         minfreq:      initial frequency [Hz]\n"
  756.     "         maxfreq:      end frequency [Hz]\n"
  757.     "         duration:     duration of the experiment [s]\n"
  758.     "         ampl_speed:   amplitude slope speed [phon/s]\n"
  759.     "         start_level:  absolute level at startup [0...1]\n"
  760.     "         earmode:      left, right, both, phase90, phase180\n"
  761.     "\n"
  762.     "example:\n"
  763.         "    ath  erb  700 22000 600 3 0.0001 > result1\n"
  764.     "    ath  erb 1400    16 360 3 0.0001 > result2\n"
  765.     "\n"
  766.     "handling:\n"
  767.     "    press '-' once when you start hearing a tone\n"
  768.     "    press '+' once when you stop hearing a tone\n"
  769.     "    press 'q' to early leave the program\n"
  770.     "    on errors the pressed key is ignored\n";
  771.     
  772.     fprintf ( stderr, "%s\n", help );
  773. }
  774.  
  775. int main ( int argc, char** argv )
  776. {
  777.     generator_t  g;
  778.     amplitude_t  a;
  779.     soundcard_t  s;
  780.     keyboard_t   k;
  781.     genmode_t    genmode;
  782.     earmode_t    earmode;
  783.  
  784.     if ( argc == 1 ) {
  785.         usage ();
  786.         system ( "./ath erb  700 22000 600 3 0.0001 > result1" );
  787.     system ( "./ath erb 1400    16 360 3 0.0001 > result2" );
  788.     system ( "xmgr result1 result2 &> /dev/null &" );
  789.     return 0;
  790.     }
  791.     
  792.     if ( argc < 6 ) {
  793.     usage ();
  794.     return 1;
  795.     }
  796.     
  797.     if      ( 0 == strncmp ( argv[1], "li" , 2) ) genmode = linear;
  798.     else if ( 0 == strncmp ( argv[1], "lo" , 2) ) genmode = logarithm;
  799.     else if ( 0 == strncmp ( argv[1], "sq" , 2) ) genmode = square;
  800.     else if ( 0 == strncmp ( argv[1], "cu" , 2) ) genmode = cubic;
  801.     else if ( 0 == strncmp ( argv[1], "er" , 2) ) genmode = erb;
  802.     else if ( 0 == strncmp ( argv[1], "re" , 2) ) genmode = recip;
  803.     else {
  804.     usage ();
  805.     return 1;
  806.     }
  807.  
  808.     if      ( argc < 8 )                              earmode = both;
  809.     else if ( 0 == strncmp ( argv[7], "le"     , 2) ) earmode = left;
  810.     else if ( 0 == strncmp ( argv[7], "ri"     , 2) ) earmode = right;
  811.     else if ( 0 == strncmp ( argv[7], "bo"     , 2) ) earmode = both;
  812.     else if ( 0 == strncmp ( argv[7], "phase9" , 6) ) earmode = phase90;
  813.     else if ( 0 == strncmp ( argv[7], "phase1" , 6) ) earmode = phase180;
  814.     else {
  815.     usage ();
  816.     return 1;
  817.     }
  818.  
  819.     
  820.     open_soundcard ( &s, AUDIO_DEVICE, sizeof(stereo_t)/sizeof(sample_t), CHAR_BIT*sizeof(sample_t), 96000.0 );
  821.     open_generator ( &g, &s, genmode, atof (argv[4]), atof (argv[2]), atof (argv[3]) );
  822.     open_amplifier ( &a, &s, argc > 6  ?  atof (argv[6])  :  0.0001, atof (argv[5]) );
  823.     open_keyboard  ( &k );
  824.  
  825.     report_open    ( );
  826.     experiment     ( &g, &a, &k, &s, earmode );
  827.     report_close   ( );
  828.     
  829.     close_keyboard ( &k );
  830.     close_amplifier( &a );
  831.     close_generator( &g );
  832.     close_soundcard( &s );
  833.     
  834.     return 0;
  835. }
  836.  
  837. /* end of ath.c */
  838.  
  839.  
  840.